using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;

namespace Admin.NET.Application.GuangHeMeter;

/// <summary>
/// 异步Socket服务器(IOCP)
/// </summary>
public class IOCPAutoServices
{
	/// <summary>
	/// 锁对象
	/// </summary>
	public object lockObj = new object();

	[CompilerGenerated]
	[DebuggerBrowsable(DebuggerBrowsableState.Never)]
	private Action<string> m_CloseDeviceEvent;

	/// <summary>
	/// 服务器程序允许的最大用户端连接数
	/// </summary>
	private int _maxClient;

	/// <summary>
	/// 监听Socket，用于接受用户端的连接请求
	/// </summary>
	private Socket _serverSock;

	/// <summary>
	/// 当前的连接的用户端数
	/// </summary>
	public int _clientCount;

	/// <summary>
	/// 用于每个I/O Socket操作的缓冲区大小 默认1024
	/// </summary>
	private int _bufferSize = 1024;

	/// <summary>
	/// 信号量
	/// </summary>
	private Semaphore _maxAcceptedClients;

	/// <summary>
	/// 对象池
	/// </summary>
	private AsyncUserTokenPool _userTokenPool;

	/// <summary>
	/// 是否释放
	/// </summary>
	private bool disposed = false;

	private SemaphoreSlim _eventLock = new SemaphoreSlim(1, 1);

	private Dictionary<string, ManualResetEvent> resetEvent = new Dictionary<string, ManualResetEvent>();

	/// <summary>
	/// 服务器是否正在运行
	/// </summary>
	public bool IsRunning { get; private set; }

	/// <summary>
	/// 监听的IP地址
	/// </summary>
	public IPAddress Address { get; private set; }

	/// <summary>
	/// 监听的端口
	/// </summary>
	public int Port { get; private set; }

	/// <summary>
	/// 通信使用的编码
	/// </summary>
	public Encoding Encoding { get; set; }

	/// <summary>
	/// 用户端的存储（SocketAsyncEventArgs为了方便发送信息 指定到指定用户）
	/// </summary>
	public ConcurrentDictionary<string, AsyncUserToken> SocketList { get; set; }

	/// <summary>
	/// 和设备绑定
	/// </summary>
	public ConcurrentDictionary<string, string> SocketDevice { get; set; }

	public int BufferSize
	{
		get
		{
			return _bufferSize;
		}
		set
		{
			_bufferSize = value;
		}
	}

	/// <summary>
	/// 接受消息处理
	/// </summary>
	public event Action<string, string, string> ReceiveMsg;

	public event Action<string> CloseDevice;

	public event Action<string> CloseDeviceEvent
	{
		[CompilerGenerated]
		add
		{
			Action<string> action = this.CloseDevice;
			Action<string> action2;
			do
			{
				action2 = action;
				Action<string> value2 = (Action<string>)Delegate.Combine(action2, value);
				action = Interlocked.CompareExchange(ref this.CloseDevice, value2, action2);
			}
			while ((object)action != action2);
		}
		[CompilerGenerated]
		remove
		{
			Action<string> action = this.CloseDevice;
			Action<string> action2;
			do
			{
				action2 = action;
				Action<string> value2 = (Action<string>)Delegate.Remove(action2, value);
				action = Interlocked.CompareExchange(ref this.CloseDevice, value2, action2);
			}
			while ((object)action != action2);
		}
	}

	public event Func<string, string> SendRecive;

	/// <summary>
	/// 异步Socket TCP服务器
	/// </summary>
	/// <param name="localEP">监听的终结点</param>
	/// <param name="maxClient">最大用户端数量</param>
	public IOCPAutoServices(IPEndPoint localEP, int maxClient)
		: this(localEP.Address, localEP.Port, maxClient)
	{
	}

	/// <summary>
	/// 异步Socket TCP服务器
	/// </summary>
	/// <param name="localIPAddress">监听的IP地址</param>
	/// <param name="listenPort">监听的端口</param>
	/// <param name="maxClient">最大用户端数量</param>
	public IOCPAutoServices(IPAddress localIPAddress, int listenPort, int maxClient)
	{
		Address = localIPAddress;
		Port = listenPort;
		Encoding = Encoding.Default;
		_maxClient = maxClient;
		_serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
		_userTokenPool = new AsyncUserTokenPool(_maxClient);
		_maxAcceptedClients = new Semaphore(_maxClient, _maxClient);
	}

	/// <summary>
	/// 初始化函数
	/// </summary>
	public void Init()
	{
		SocketList = new ConcurrentDictionary<string, AsyncUserToken>();
		SocketDevice = new ConcurrentDictionary<string, string>();
		for (int i = 0; i < _maxClient; i++)
		{
			AsyncUserToken userToken = new AsyncUserToken(_bufferSize * 50);
			userToken.ReceiveEventArgs.Completed += OnIOCompleted;
			userToken.SendEventArgs.Completed += OnIOCompleted;
			_userTokenPool.Push(userToken);
		}
	}

	/// <summary>
	/// 启动
	/// </summary>
	public void Start()
	{
		if (!IsRunning)
		{
			Init();
			IsRunning = true;
			IPEndPoint localEndPoint = new IPEndPoint(Address, Port);
			_serverSock = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
			{
				_serverSock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, optionValue: false);
				_serverSock.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
			}
			else
			{
				_serverSock.Bind(localEndPoint);
			}
			_serverSock.Listen(_maxClient);
			StartAccept(null);
		}
	}

	/// <summary>
	/// 停止服务
	/// </summary>
	public void Stop()
	{
		if (IsRunning)
		{
			IsRunning = false;
			_serverSock.Close();
		}
	}

	/// <summary>
	/// 从用户端开始接受一个连接操作==
	/// </summary>
	private void StartAccept(SocketAsyncEventArgs asyniar)
	{
		BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
		if (asyniar == null)
		{
			asyniar = new SocketAsyncEventArgs();
			asyniar.Completed += OnAcceptCompleted;
		}
		else
		{
			int reciveInt = (int)asyniar.GetType().GetField("_operating", flag).GetValue(asyniar);
			asyniar.AcceptSocket = null;
		}
		_maxAcceptedClients.WaitOne();
		string msg = "sss12sss";
		if (!_serverSock.AcceptAsync(asyniar))
		{
			LoggerExtension.Debug("进入了123");
			ProcessAccept(asyniar, msg);
			LoggerExtension.Debug("出去了456");
		}
		int a = (int)asyniar.GetType().GetField("_operating", flag).GetValue(asyniar);
	}

	/// <summary>
	/// accept 操作完成时回调函数
	/// </summary>
	/// <param name="sender"></param>
	/// <param name="e"></param>
	private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e)
	{
		BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
		int reciveInt = (int)e.GetType().GetField("_operating", flag).GetValue(e);
		ProcessAccept(e, "556");
	}

	private byte[] KeepAlive(int onOff, int keepAliveTime, int keepAliveInterval)
	{
		byte[] buffer = new byte[12];
		BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
		BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
		BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
		return buffer;
	}

	/// <summary>
	/// 监听Socket接受处理
	/// </summary>
	/// <param name="e">监听的socket</param>
	private void ProcessAccept(SocketAsyncEventArgs e, string msg = "")
	{
		AsyncUserToken userToken = null;
		msg += "123";
		try
		{
			if (e.SocketError != 0)
			{
				return;
			}
			Socket sock = e.AcceptSocket;
			if (!sock.Connected)
			{
				return;
			}
			sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, optionValue: true);
			BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
			userToken = _userTokenPool.Pop();
			Interlocked.Increment(ref _clientCount);
			msg += "88888";
			int reciveInt = (int)userToken.ReceiveEventArgs.GetType().GetField("_operating", flag).GetValue(userToken.ReceiveEventArgs);
			userToken.ConnectSocket = sock;
			msg += "99999";
			string address = userToken.ConnectSocket.RemoteEndPoint.ToString();
			e.UserToken = userToken;
			SocketList.TryAdd(address, userToken);
			msg = msg + "333333----" + reciveInt;
			if (reciveInt != 1)
			{
				if (!sock.ReceiveAsync(userToken.ReceiveEventArgs))
				{
					msg += "5555";
					ProcessReceive(userToken.ReceiveEventArgs);
					msg += "666666";
				}
			}
			else
			{
				LoggerExtension.Error("当前未释放", new Exception());
			}
			msg += "4444";
			LoggerExtension.Info($"当前设备已连接{address}连接数为：{SocketList.Count}");
		}
		catch (Exception ex)
		{
			if (userToken != null)
			{
				CloseClientSocket(userToken, "123");
			}
			LoggerExtension.Error("执行报错11" + ex.Message + msg, ex);
		}
		finally
		{
			StartAccept(e);
		}
	}

	/// <summary>
	/// 异步的发送数据
	/// </summary>
	/// <param name="deviceManagerCode"></param>
	/// <param name="data"></param>
	public void Send(string deviceManagerCode, byte[] data, out string msg)
	{
		msg = "";
		string keyDevice = SocketDevice.Where((KeyValuePair<string, string> u) => u.Value == deviceManagerCode).FirstOrDefault().Key;
		if (string.IsNullOrEmpty(keyDevice))
		{
			msg = "当前设备已离线";
			return;
		}
		if (!SocketList.TryGetValue(keyDevice, out var userToken))
		{
			msg = "当前设备已离线";
			return;
		}
		if (userToken == null)
		{
			msg = "当前设备已离线";
			SocketDevice.TryRemove(keyDevice, out var _);
			return;
		}
		userToken.SendBuffer.WriteBuffer(data, 0, data.Length);
		if (userToken.SendEventArgs.SocketError == SocketError.Success)
		{
			if (userToken.ConnectSocket.Connected)
			{
				userToken.SendEventArgs.SetBuffer(userToken.SendBuffer.Buffer, 0, userToken.SendBuffer.DataCount);
				if (userToken.ConnectSocket.SendAsync(userToken.SendEventArgs))
				{
				}
				userToken.SendBuffer.Clear();
			}
			else
			{
				CloseClientSocket(userToken, "333");
			}
		}
		else
		{
			CloseClientSocket(userToken, "5555");
		}
	}

	private string ToHexString(byte[] bytes)
	{
		string hexString = string.Empty;
		if (bytes != null)
		{
			for (int i = 0; i < bytes.Length; i++)
			{
				hexString = hexString + bytes[i].ToString("X2") + " ";
			}
		}
		return hexString;
	}

	/// <summary>
	/// 异步的发送数据
	/// </summary>
	/// <param name="deviceManagerCode"></param>
	/// <param name="data"></param>
	public void Send(string deviceCode, byte[] data)
	{
		LoggerExtension.Info("正在发送数据:" + ToHexString(data));
		AsyncUserToken userToken = null;
		if (!SocketList.TryGetValue(deviceCode, out userToken))
		{
			SocketDevice.TryRemove(deviceCode, out var _);
			return;
		}
		if (userToken == null)
		{
			SocketDevice.Remove(deviceCode, out var _);
			return;
		}
		userToken.SendBuffer.WriteBuffer(data, 0, data.Length);
		if (userToken.SendEventArgs.SocketError == SocketError.Success && !userToken.IsDispose)
		{
			if (userToken.ConnectSocket.Connected)
			{
				userToken.SendEventArgs.SetBuffer(userToken.SendBuffer.Buffer, 0, userToken.SendBuffer.DataCount);
				if (userToken.ConnectSocket.SendAsync(userToken.SendEventArgs))
				{
				}
				userToken.SendBuffer.Clear();
			}
			else
			{
				CloseClientSocket(userToken, "6666");
			}
		}
		else
		{
			CloseClientSocket(userToken, "777");
		}
	}

	/// <summary>
	/// 异步的发送数据
	/// </summary>
	/// <param name="userToken"></param>
	/// <param name="data"></param>
	private void Send(byte[] data, AsyncUserToken userToken)
	{
		userToken.SendBuffer.WriteBuffer(data, 0, data.Length);
		if (userToken.SendEventArgs.SocketError == SocketError.Success)
		{
			if (userToken.ConnectSocket.Connected)
			{
				userToken.SendEventArgs.SetBuffer(userToken.SendBuffer.Buffer, 0, userToken.SendBuffer.DataCount);
				userToken.SendBuffer.Clear();
			}
			else
			{
				CloseClientSocket(userToken, "888");
			}
		}
		else
		{
			CloseClientSocket(userToken, "999");
		}
	}

	/// <summary>
	/// 同步的使用socket发送数据
	/// </summary>
	/// <param name="socket"></param>
	/// <param name="buffer"></param>
	/// <param name="offset"></param>
	/// <param name="size"></param>
	/// <param name="timeout"></param>
	public void Send(Socket socket, byte[] buffer, int offset, int size, int timeout)
	{
		socket.SendTimeout = 0;
		int startTickCount = Environment.TickCount;
		int sent = 0;
		do
		{
			if (Environment.TickCount > startTickCount + timeout)
			{
			}
			try
			{
				sent += socket.Send(buffer, offset + sent, size - sent, SocketFlags.None);
			}
			catch (SocketException ex)
			{
				if (ex.SocketErrorCode == SocketError.WouldBlock || ex.SocketErrorCode == SocketError.IOPending || ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
				{
					Thread.Sleep(30);
					continue;
				}
				throw ex;
			}
		}
		while (sent < size);
	}

	public ManualResetEvent GetResetEvent(string key)
	{
		if (resetEvent.ContainsKey(key))
		{
			return resetEvent[key];
		}
		return null;
	}

	public void SendReset(string deviceCode, byte[] data)
	{
		string keyDevice = "";
		keyDevice = SocketDevice.Where((KeyValuePair<string, string> u) => u.Value == deviceCode).FirstOrDefault().Key;
		if (!string.IsNullOrEmpty(keyDevice))
		{
			Send(keyDevice, data);
		}
	}

	/// <summary>
	/// 发送完成时处理函数
	/// </summary>
	/// <param name="e">与发送完成操作相关联的SocketAsyncEventArg对象</param>
	private void ProcessSend(SocketAsyncEventArgs e)
	{
		AsyncUserToken userToken = e.UserToken as AsyncUserToken;
		if (userToken.SendEventArgs.SocketError != 0)
		{
			CloseClientSocket(userToken, "qqqqq");
		}
	}

	/// <summary>
	///             接收完成时处理函数（接受客户端发来的消息）
	/// </summary>
	/// <param name="e">与接收完成操作相关联的SocketAsyncEventArg对象</param>
	private void ProcessReceive(SocketAsyncEventArgs e)
	{
		AsyncUserToken userToken = e.UserToken as AsyncUserToken;
		string address = "";
		try
		{
			if (!userToken.IsDispose && userToken.ConnectSocket.Connected && userToken.ReceiveEventArgs.BytesTransferred > 0 && userToken.ReceiveEventArgs.SocketError == SocketError.Success && SocketList.ContainsKey(userToken.ConnectSocket.RemoteEndPoint?.ToString()))
			{
				address = userToken.ConnectSocket.RemoteEndPoint?.ToString();
				Socket sock = userToken.ConnectSocket;
				if (sock.Available == 0)
				{
					userToken.ReceiveBuffer.WriteBuffer(e.Buffer, e.Offset, e.BytesTransferred);
					string deviceinfo = null;
					SocketDevice.TryGetValue(address, out deviceinfo);
					if (deviceinfo == null)
					{
						deviceinfo = address;
					}
					Span<byte> byteinfo = new Span<byte>(e.Buffer, e.Offset, e.BytesTransferred);
					this.ReceiveMsg(Encoding.UTF8.GetString(byteinfo), deviceinfo, address);
				}
				if (!sock.ReceiveAsync(userToken.ReceiveEventArgs))
				{
					ProcessReceive(userToken.ReceiveEventArgs);
				}
			}
			else
			{
				LoggerExtension.Debug("sssssssssssssssssss当前开始关闭" + address);
				CloseClientSocket(userToken, "wwwwwww");
			}
		}
		catch (Exception ex)
		{
			CloseClientSocket(userToken, "tttttt");
			LoggerExtension.Error("当前解析失败报错11" + ex.Message, ex);
		}
	}

	/// <summary>
	/// 当Socket上的发送或接收请求被完成时，调用此函数
	/// </summary>
	/// <param name="sender">激发事件的对象</param>
	/// <param name="e">与发送或接收完成操作相关联的SocketAsyncEventArg对象</param>
	private void OnIOCompleted(object sender, SocketAsyncEventArgs e)
	{
		AsyncUserToken userToken = e.UserToken as AsyncUserToken;
		lock (userToken)
		{
			switch (e.LastOperation)
			{
			case SocketAsyncOperation.Accept:
				ProcessAccept(e, "999");
				break;
			case SocketAsyncOperation.Receive:
				ProcessReceive(e);
				break;
			case SocketAsyncOperation.Send:
				ProcessSend(e);
				break;
			case SocketAsyncOperation.Disconnect:
				CloseClientSocket((AsyncUserToken)e.UserToken, "pssqqqqqq");
				break;
			default:
				throw new ArgumentException("当前未有");
			}
		}
	}

	/// <summary>
	/// 关闭连接 对外
	/// </summary>
	/// <param name="deviceId">设备资产编号</param>
	public void CloseClientByApi(string deviceId)
	{
		string keyDevice = "";
		keyDevice = SocketDevice.Where((KeyValuePair<string, string> u) => u.Value == deviceId).FirstOrDefault().Key;
		if (!string.IsNullOrEmpty(keyDevice))
		{
			CloseClient(keyDevice);
		}
	}

	/// <summary>
	/// 关闭连接 对外
	/// </summary>
	/// <param name="deviceId"></param>
	public void CloseClient(string deviceId, bool closeAny = true)
	{
		if (SocketList.TryGetValue(deviceId, out var sockert) && sockert != null)
		{
			CloseClientSocket(sockert, closeAny);
		}
	}

	/// <summary>
	/// 关闭连接 对外
	/// </summary>
	/// <param name="deviceId"></param>
	public void CloseClientManagerId(string deviceManagerId, bool closeAny = true)
	{
		KeyValuePair<string, string> sockertValue = default(KeyValuePair<string, string>);
		sockertValue = SocketDevice.Where((KeyValuePair<string, string> u) => u.Value == deviceManagerId).FirstOrDefault();
		if (SocketList.TryGetValue(sockertValue.Key ?? "", out var sockert))
		{
			CloseClientSocket(sockert, closeAny);
		}
	}

	/// <summary>
	/// 关闭socket连接
	/// </summary>
	/// <param name="e">SocketAsyncEventArg associated with the completed send/receive operation.</param>
	private void CloseClientSocket(AsyncUserToken userToken, bool closeAny = true)
	{
		string device = "";
		try
		{
			device = SocketList.Where((KeyValuePair<string, AsyncUserToken> u) => u.Value == userToken).FirstOrDefault().Key;
			if (!string.IsNullOrEmpty(device))
			{
				LoggerExtension.Info("开始关闭设备" + device + "当前关闭状态" + closeAny + "当前设备状态" + userToken.IsDispose + userToken?.ConnectSocket?.Connected);
				if (SocketDevice.TryGetValue(device, out var value) && closeAny)
				{
					this.CloseDevice(value);
				}
				if (userToken.ConnectSocket != null)
				{
					userToken.ConnectSocket.Shutdown(SocketShutdown.Send);
				}
			}
		}
		catch (Exception)
		{
		}
		finally
		{
			if (!string.IsNullOrEmpty(device))
			{
				SocketList.TryRemove(device ?? "", out var _);
				SocketDevice.TryRemove(device ?? "", out var _);
			}
			if (userToken.ConnectSocket != null)
			{
				userToken.CloseDispose();
			}
			userToken.ConnectSocket = null;
			int count = 0;
			_userTokenPool.Push(userToken, _maxAcceptedClients, ref count);
			LoggerExtension.Debug("当前数据" + count);
		}
		LoggerExtension.Debug("进入了 " + device);
	}

	private void CloseClientSocket(AsyncUserToken userToken, string msg)
	{
		bool closeAny = true;
		string device = "";
		try
		{
			device = SocketList.Where((KeyValuePair<string, AsyncUserToken> u) => u.Value == userToken).FirstOrDefault().Key;
			if (!string.IsNullOrEmpty(device))
			{
				LoggerExtension.Info(msg + "ss1开始关闭设备" + device + "当前关闭状态" + closeAny + "当前设备状态" + userToken.IsDispose + userToken?.ConnectSocket?.Connected);
				if (SocketDevice.TryGetValue(device, out var value) && closeAny)
				{
					this.CloseDevice(value);
				}
				if (userToken.ConnectSocket != null)
				{
					userToken.ConnectSocket.Shutdown(SocketShutdown.Send);
				}
			}
		}
		catch (Exception)
		{
		}
		finally
		{
			if (!string.IsNullOrEmpty(device))
			{
				SocketList.TryRemove(device ?? "", out var _);
				SocketDevice.TryRemove(device ?? "", out var _);
			}
			this.CloseDevice(device);
			if (userToken.ConnectSocket != null)
			{
				userToken.CloseDispose();
			}
			userToken.ConnectSocket = null;
			int count = 0;
			_userTokenPool.Push(userToken, _maxAcceptedClients, ref count);
			LoggerExtension.Debug("当前数据" + count);
		}
		LoggerExtension.Debug("进入了 " + device);
	}

	/// <summary>
	/// 设备录入本地
	/// </summary>
	/// <param name="deviceId"></param>
	/// <param name="managerId"></param>
	public void SocketDeviceAdd(string deviceId, string managerId)
	{
		if (SocketDevice.ContainsKey(deviceId))
		{
			SocketDevice.TryRemove(deviceId, out var _);
		}
		SocketDevice.TryAdd(deviceId, managerId);
	}

	/// <summary>
	/// 回收
	/// Performs application-defined tasks associated with freeing, 
	/// releasing, or resetting unmanaged resources.
	/// </summary>
	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	/// <summary>
	/// Releases unmanaged and - optionally - managed resources
	/// </summary>
	/// <param name="disposing"><c>true</c> to release 
	/// both managed and unmanaged resources; <c>false</c> 
	/// to release only unmanaged resources.</param>
	protected virtual void Dispose(bool disposing)
	{
		if (disposed)
		{
			return;
		}
		if (disposing)
		{
			try
			{
				Stop();
				if (_serverSock != null)
				{
					_serverSock = null;
				}
			}
			catch (SocketException)
			{
			}
		}
		disposed = true;
	}
}
